package pipe

import (
	"context"
	"gitee.com/injoyai/goutil/net/conn/v2"
	"gitee.com/injoyai/goutil/net/tcp/v2"
	"log"
)

// NewServer 新建服务,里面包含了服务端,提供对外写入接口,默认base64加密
func NewServer(port int) (*Server, error) {
	return NewServerWithContext(context.Background(), port)
}

func NewServerWithContext(ctx context.Context, port int) (*Server, error) {
	pipeServer, err := tcp.NewServerWithContext(ctx, port)
	if err != nil {
		return nil, err
	}
	ctx, cancel := context.WithCancel(ctx)
	s := &Server{
		Server: pipeServer.
			SetPrintFunc(PrintWithServer).
			SetBeforeFunc(BeforeWithServer).
			SetReadFunc(ReadWithBase64).
			SetWriteFunc(WriteWithBase64).
			SetTimeout(DefaultKeepAlive * 3),
		dealRead: func(c *conn.Conn, msg *Message) { log.Printf("[响应][%s] %s\n", msg.Key, msg.Data) },
		ctx:      ctx,
		cancel:   cancel,
	}
	s.Server.SetDealFunc(s.dealFunc)
	return s, nil
}

type Server struct {
	Server    *tcp.Server
	dealRead  func(c *conn.Conn, msg *Message)                 //处理读到的数据
	dealWrite func(sn, key, addr, data string) (string, error) // 处理写入的数据,例如修改请求头...
	ctx       context.Context
	cancel    context.CancelFunc
	//client    *maps.Safe
}

// SetEncryptAESCBC 设置数据加密方式 AES CBC
func (this *Server) SetEncryptAESCBC(key []byte, iv ...[]byte) *Server {
	this.Server.SetWriteFunc(NewWriteAESCBC(key, iv...))
	this.Server.SetReadFunc(NewReadAESCBC(key, iv...))
	return this
}

// Debug 调试模式
func (this *Server) Debug(b ...bool) {
	this.Server.Debug(b...)
}

// SetDealWriteFunc 设置写入通道的数据,例如修改请求头,过滤非法请求等...
func (this *Server) SetDealWriteFunc(fn func(sn, key, addr, data string) (string, error)) *Server {
	this.dealWrite = fn
	return this
}

// SetDealReadFunc 设置读取通道的数据,
func (this *Server) SetDealReadFunc(fn func(c *conn.Conn, msg *Message)) *Server {
	this.dealRead = fn
	return this
}

// SetDealCloseFunc 设置通道客户端关闭事件
func (this *Server) SetDealCloseFunc(fn func(c *conn.Conn, msg *Message)) *Server {
	this.Server.SetCloseFunc(func(m *conn.Message) {
		msg, _ := decodeMsg(m.Bytes())
		fn(m.Client(), msg)
	})
	return this
}

// Close 关闭通道服务
func (this *Server) Close() {
	if this.cancel != nil {
		this.cancel()
	}
}

// Run 开始通道服务
func (this *Server) Run() error {
	return this.Server.Run()
}

func (this *Server) CloseProxy(pipeSn, clientKey, data string) {
	msg := newCloseMsg(clientKey, data)
	pipe := this.Server.GetConn(pipeSn)
	if pipe != nil {
		pipe.WriteBytes(msg.Bytes())
	}
}

// WriteProxy 向通道客户端发送数据 pipeSn(conn)>clientKey(client addr)>proxyAddr(remote addr)
func (this *Server) WriteProxy(pipeSn, clientKey, proxyAddr, data string) (err error) {
	msg := newWriteMsg(clientKey, proxyAddr, data)
	pipe := this.Server.GetConn(pipeSn)
	if pipe == nil {
		return ErrNoConnected
	}
	if this.dealWrite != nil {
		data, err = this.dealWrite(pipeSn, clientKey, proxyAddr, data)
		if err != nil {
			msg = newCloseMsg(clientKey, err.Error())
		}
	}
	return pipe.WriteBytes(msg.Bytes())
}

// dealFunc 数据处理
func (this *Server) dealFunc(msg *conn.Message) {
	if this.dealRead != nil {
		// 解析通道客户端发送的数据
		m, err := decodeMsg(msg.Bytes())
		if err != nil {
			return
		}
		if m.Type == Register {
			// 通道客户端注册信息,修改连接key
			this.Server.SetConnKey(msg.Client(), m.Key)
			return
		}
		// 根据设置的处理函数处理数据
		this.dealRead(msg.Client(), m)
	}
}
